package es.andresimon.portfolio.domain;

import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import java.util.Date;
import java.util.List;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EntityManager;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.persistence.Version;
import org.springframework.beans.factory.annotation.Configurable;
import org.springframework.format.annotation.DateTimeFormat;
import es.andresimon.portfolio.security.UserRole;
import javax.persistence.Enumerated;

@Configurable
@Entity
public class Project {

    private Long projectId;

    private Integer weight;

    @NotNull
    @Size(min = 1, max = 50)
    private String title;

    @Temporal(TemporalType.TIMESTAMP)
    @DateTimeFormat(style = "S-")
    private Date projectDate;

    @NotNull
    private Long frontPicture;

    @NotNull
    @Size(min = 1, max = 4000)
    private String introduction;

    @NotNull
    @Size(min = 1, max = 10000)
    private String column1;

    @Size(min = 0, max = 10000)
    private String column2;

    private Boolean visibility;

    @Size(min = 0, max = 500)
    private String url;

    @Size(min = 0, max = 1000)
    private String video;

    @Enumerated
    private UserRole userRole;

	public static Query findProjectsByUserRole(UserRole userRole) {
        if (userRole == null) throw new IllegalArgumentException("The userRole argument is required");
        EntityManager em = Project.entityManager();
        Query q = em.createQuery("SELECT Project FROM Project AS project WHERE project.userRole = :userRole");
        q.setParameter("userRole", userRole);
        return q;
    }

	public Long getProjectId() {
        return this.projectId;
    }

	public void setProjectId(Long projectId) {
        this.projectId = projectId;
    }

	public Integer getWeight() {
        return this.weight;
    }

	public void setWeight(Integer weight) {
        this.weight = weight;
    }

	public String getTitle() {
        return this.title;
    }

	public void setTitle(String title) {
        this.title = title;
    }

	public Date getProjectDate() {
        return this.projectDate;
    }

	public void setProjectDate(Date projectDate) {
        this.projectDate = projectDate;
    }

	public Long getFrontPicture() {
        return this.frontPicture;
    }

	public void setFrontPicture(Long frontPicture) {
        this.frontPicture = frontPicture;
    }

	public String getIntroduction() {
        return this.introduction;
    }

	public void setIntroduction(String introduction) {
        this.introduction = introduction;
    }

	public String getColumn1() {
        return this.column1;
    }

	public void setColumn1(String column1) {
        this.column1 = column1;
    }

	public String getColumn2() {
        return this.column2;
    }

	public void setColumn2(String column2) {
        this.column2 = column2;
    }

	public Boolean getVisibility() {
        return this.visibility;
    }

	public void setVisibility(Boolean visibility) {
        this.visibility = visibility;
    }

	public String getUrl() {
        return this.url;
    }

	public void setUrl(String url) {
        this.url = url;
    }

	public String getVideo() {
        return this.video;
    }

	public void setVideo(String video) {
        this.video = video;
    }

	public UserRole getUserRole() {
        return this.userRole;
    }

	public void setUserRole(UserRole userRole) {
        this.userRole = userRole;
    }

	public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append("Id: ").append(getId()).append(", ");
        sb.append("Version: ").append(getVersion()).append(", ");
        sb.append("ProjectId: ").append(getProjectId()).append(", ");
        sb.append("Weight: ").append(getWeight()).append(", ");
        sb.append("Title: ").append(getTitle()).append(", ");
        sb.append("ProjectDate: ").append(getProjectDate()).append(", ");
        sb.append("FrontPicture: ").append(getFrontPicture()).append(", ");
        sb.append("Introduction: ").append(getIntroduction()).append(", ");
        sb.append("Column1: ").append(getColumn1()).append(", ");
        sb.append("Column2: ").append(getColumn2()).append(", ");
        sb.append("Visibility: ").append(getVisibility()).append(", ");
        sb.append("Url: ").append(getUrl()).append(", ");
        sb.append("Video: ").append(getVideo()).append(", ");
        sb.append("UserRole: ").append(getUserRole());
        return sb.toString();
    }

	@PersistenceContext
    transient EntityManager entityManager;

	@Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    private Long id;

	@Version
    @Column(name = "version")
    private Integer version;

	public Long getId() {
        return this.id;
    }

	public void setId(Long id) {
        this.id = id;
    }

	public Integer getVersion() {
        return this.version;
    }

	public void setVersion(Integer version) {
        this.version = version;
    }

	@Transactional(propagation = Propagation.REQUIRES_NEW)
    public void persist() {
        if (this.entityManager == null) this.entityManager = entityManager();
        this.entityManager.persist(this);
    }

	@Transactional
    public void remove() {
        if (this.entityManager == null) this.entityManager = entityManager();
        if (this.entityManager.contains(this)) {
            this.entityManager.remove(this);
        } else {
            Project attached = this.entityManager.find(this.getClass(), this.id);
            this.entityManager.remove(attached);
        }
    }

	@Transactional
    public void flush() {
        if (this.entityManager == null) this.entityManager = entityManager();
        this.entityManager.flush();
    }

	@Transactional
    public Project merge() {
        if (this.entityManager == null) this.entityManager = entityManager();
        Project merged = this.entityManager.merge(this);
        this.entityManager.flush();
        return merged;
    }

	public static final EntityManager entityManager() {
        EntityManager em = new Project().entityManager;
        if (em == null) throw new IllegalStateException("Entity manager has not been injected (is the Spring Aspects JAR configured as an AJC/AJDT aspects library?)");
        return em;
    }

	@Transactional
    public static long countProjects() {
        return ((Number) entityManager().createQuery("select count(o) from Project o").getSingleResult()).longValue();
    }

	@SuppressWarnings("unchecked")
    @Transactional
    public static List<Project> findAllProjects() {
        return entityManager().createQuery("select o from Project o").getResultList();
    }

	@Transactional
    public static Project findProject(Long id) {
        if (id == null) return null;
        return entityManager().find(Project.class, id);
    }

	@SuppressWarnings("unchecked")
    @Transactional
    public static List<Project> findProjectEntries(int firstResult, int maxResults) {
        return entityManager().createQuery("select o from Project o").setFirstResult(firstResult).setMaxResults(maxResults).getResultList();
    }
}
